#include "qos/qospolicycheck.h"
#include "common/log/logger.h" 
USING_AGIDDS_NAMESPACE
ReturnCode_t QosPolicyCheck::CheckQos(const DomainParticipantFactoryQos& qos)
{
	/* yuguxu 所包含QoS无规范限制 */
	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckQos(const DomainParticipantQos& qos)
{
	/* yuguxu 所包含QoS无规范限制 */
	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckQos(const PublisherQos& qos)
{
	/* yuguxu 所包含QoS无规范限制 */
	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckQos(const SubscriberQos& qos)
{
	/* yuguxu 所包含QoS无规范限制 */
	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckQos(const TopicQos& qos)
{
	ReturnCode_t ret = RETCODE_OK;
	/* HISTORY, RESOURCE_LIMITS */
	ret = CheckHistoryAndResourcueLimits(qos.history, qos.resource_limits);
	if (RETCODE_OK != ret) {
		return ret;
	}

	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckQos(const DataWriterQos& qos)
{
	ReturnCode_t ret = RETCODE_OK;
	/* HISTORY, RESOURCE_LIMITS */
	ret = CheckHistoryAndResourcueLimits(qos.history, qos.resource_limits);
	if (RETCODE_OK != ret) {
		AGILOG(AGILOG_ERROR, "CheckQos History and ResourceLimits Err");
		return ret;
	}

	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckQos(const DataReaderQos& qos)
{
	ReturnCode_t ret = RETCODE_OK;
	/* HISTORY, RESOURCE_LIMITS */
	ret = CheckHistoryAndResourcueLimits(qos.history,qos.resource_limits);
	if (RETCODE_OK != ret) {
		AGILOG(AGILOG_ERROR, "CheckQos History and ResourceLimits Err");
		return ret;
	}
	/* DEADLINE, TIME_BASED_FILTER */
	ret = CheckDeadlineAndTimeBasedFilter(qos.deadline,qos.time_based_filter);
	if (RETCODE_OK != ret) {
		AGILOG(AGILOG_ERROR, "CheckQos DeadLine and TimeBased Err");
		return ret;
	}
	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckHistoryAndResourcueLimits(const HistoryQosPolicy& historyQos, const ResourceLimitsQosPolicy& resourceLimitsQos)
{
	if (historyQos.kind == KEEP_LAST_HISTORY_QOS && historyQos.depth <= 0) {
		AGILOG(AGILOG_ERROR, "Error historyQos.kind == KEEP_LAST_HISTORY_QOS && historyQos.depth <= 0");
		return RETCODE_INCONSISTENT_POLICY;
	}
	/* history.kind == KEEP_LAST_HISTORY_QOS && history.depth > 0 */
	if (historyQos.kind == KEEP_LAST_HISTORY_QOS && 
	    historyQos.depth > resourceLimitsQos.max_samples_per_instance && 
		resourceLimitsQos.max_samples_per_instance != static_cast<int32_t>(LENGTH_UNLIMITED)) {
		AGILOG(AGILOG_ERROR, "historyQos.depth[%d] > resourceLimitsQos.max_samples_per_instance[%d] && resourceLimitsQos.max_samples_per_instance[%d] != static_cast<int32_t>(LENGTH_UNLIMITED)", historyQos.depth, resourceLimitsQos.max_samples_per_instance, resourceLimitsQos.max_samples_per_instance);
		return RETCODE_INCONSISTENT_POLICY;
	}
	if (resourceLimitsQos.max_samples > 0 &&
		((resourceLimitsQos.max_instances <= 0 || resourceLimitsQos.max_samples_per_instance <= 0) ||
		(resourceLimitsQos.max_samples < (resourceLimitsQos.max_instances * resourceLimitsQos.max_samples_per_instance)))) {
		AGILOG(AGILOG_ERROR, "resourceLimitsQos.max_samples[%d] > 0 && \
			((resourceLimitsQos.max_instances[%d] <= 0 || resourceLimitsQos.max_samples_per_instance[%d] <= 0) || \
			(resourceLimitsQos.max_samples[%d] < (resourceLimitsQos.max_instances[%d] * resourceLimitsQos.max_samples_per_instance[%d]))", resourceLimitsQos.max_samples, resourceLimitsQos.max_instances, resourceLimitsQos.max_samples_per_instance, resourceLimitsQos.max_samples,resourceLimitsQos.max_instances, resourceLimitsQos.max_samples_per_instance);
		return RETCODE_INCONSISTENT_POLICY;
	}
	return RETCODE_OK;
}

ReturnCode_t QosPolicyCheck::CheckDeadlineAndTimeBasedFilter(const DeadlineQosPolicy& deadline, const TimeBasedFilterQosPolicy& timeBasedFilter)
{
	/* 设置必须是“deadline period > = minimum_separation” */
	if (deadline.period < timeBasedFilter.minimum_separation) {
		AGILOG(AGILOG_ERROR, "Error deadline.period[%d.%d] < timeBasedFilter.minimum_separation[%d.%d]", deadline.period.sec, deadline.period.nanosec, timeBasedFilter.minimum_separation.sec, timeBasedFilter.minimum_separation.nanosec);
		return RETCODE_INCONSISTENT_POLICY;
	}
	return RETCODE_OK;
}


bool QosPolicyCheck::CanQosBeUpdated(const DomainParticipantFactoryQos& curQos, const DomainParticipantFactoryQos& tagQos)
{
	/* yuguxu 所包含QoS无不可更改 */
	return true;
}

bool QosPolicyCheck::CanQosBeUpdated(const DomainParticipantQos& curQos, const DomainParticipantQos& tagQos)
{
	/* yuguxu 所包含QoS无不可更改 */
	return true;
}

bool QosPolicyCheck::CanQosBeUpdated(const PublisherQos& curQos, const PublisherQos& tagQos)
{
	return ConsistebcyCheckPresentationQos(curQos.presentation,tagQos.presentation);
}

bool QosPolicyCheck::CanQosBeUpdated(const SubscriberQos& curQos, const SubscriberQos& tagQos)
{
	return ConsistebcyCheckPresentationQos(curQos.presentation, tagQos.presentation);
}

bool QosPolicyCheck::CanQosBeUpdated(const TopicQos& curQos, const TopicQos& tagQos)
{
	return ConsistebcyCheckDurabilityQos(curQos.durability, tagQos.durability) &&
		   ConsistebcyCheckDurabilityServiceQos(curQos.durability_service, tagQos.durability_service) &&
		   ConsistebcyCheckOwnershipQos(curQos.ownership, tagQos.ownership) &&
		   ConsistebcyCheckLivelinessQos(curQos.liveliness, tagQos.liveliness) &&
		   ConsistebcyCheckReliabilityQos(curQos.reliability, tagQos.reliability) &&
		   ConsistebcyCheckDestinationOrderQos(curQos.destination_order, tagQos.destination_order) &&
		   ConsistebcyCheckHistoryQos(curQos.history, tagQos.history) &&
		   ConsistebcyCheckResourceLimitsQos(curQos.resource_limits, tagQos.resource_limits);
}

bool QosPolicyCheck::CanQosBeUpdated(const DataWriterQos& curQos, const DataWriterQos& tagQos)
{
	return ConsistebcyCheckDurabilityQos(curQos.durability, tagQos.durability) &&
		   ConsistebcyCheckDurabilityServiceQos(curQos.durability_service, tagQos.durability_service) &&
		   ConsistebcyCheckOwnershipQos(curQos.ownership, tagQos.ownership) &&
		   ConsistebcyCheckLivelinessQos(curQos.liveliness, tagQos.liveliness) &&
		   ConsistebcyCheckReliabilityQos(curQos.reliability, tagQos.reliability) &&
		   ConsistebcyCheckDestinationOrderQos(curQos.destination_order, tagQos.destination_order) &&
		   ConsistebcyCheckHistoryQos(curQos.history, tagQos.history) &&
		   ConsistebcyCheckResourceLimitsQos(curQos.resource_limits, tagQos.resource_limits);
}

bool QosPolicyCheck::CanQosBeUpdated(const DataReaderQos& curQos, const DataReaderQos& tagQos)
{
	return ConsistebcyCheckDurabilityQos(curQos.durability, tagQos.durability) &&
		   ConsistebcyCheckOwnershipQos(curQos.ownership, tagQos.ownership) &&
		   ConsistebcyCheckLivelinessQos(curQos.liveliness, tagQos.liveliness) &&
		   ConsistebcyCheckReliabilityQos(curQos.reliability, tagQos.reliability) &&
		   ConsistebcyCheckDestinationOrderQos(curQos.destination_order, tagQos.destination_order) &&
		   ConsistebcyCheckHistoryQos(curQos.history, tagQos.history) &&
		   ConsistebcyCheckResourceLimitsQos(curQos.resource_limits, tagQos.resource_limits);
}

bool QosPolicyCheck::ConsistebcyCheckDurabilityQos(const DurabilityQosPolicy& qosA, const DurabilityQosPolicy& qosB)
{
	return qosA.kind == qosB.kind;
}

bool QosPolicyCheck::ConsistebcyCheckDurabilityServiceQos(const DurabilityServiceQosPolicy& qosA, const DurabilityServiceQosPolicy& qosB)
{
	return (qosA.service_cleanup_delay == qosB.service_cleanup_delay) &&
	       (qosA.history_kind == qosB.history_kind) &&
	       (qosA.history_depth == qosB.history_depth) &&
	       (qosA.max_samples == qosB.max_samples) &&
	       (qosA.max_instances == qosB.max_instances) &&
	       (qosA.max_samples_per_instance == qosB.max_samples_per_instance);
}

bool QosPolicyCheck::ConsistebcyCheckOwnershipQos(const OwnershipQosPolicy& qosA, const OwnershipQosPolicy& qosB)
{
	return qosA.kind == qosB.kind;
}

bool QosPolicyCheck::ConsistebcyCheckLivelinessQos(const LivelinessQosPolicy& qosA, const LivelinessQosPolicy& qosB)
{
	return (qosA.kind == qosB.kind) &&
		   (qosA.lease_duration == qosB.lease_duration);
}

bool QosPolicyCheck::ConsistebcyCheckReliabilityQos(const ReliabilityQosPolicy& qosA, const ReliabilityQosPolicy& qosB)
{
	return (qosA.kind == qosB.kind) &&
		   (qosA.max_blocking_time == qosB.max_blocking_time);
}

bool QosPolicyCheck::ConsistebcyCheckDestinationOrderQos(const DestinationOrderQosPolicy& qosA, const DestinationOrderQosPolicy& qosB)
{
	return qosA.kind == qosB.kind;
}

bool QosPolicyCheck::ConsistebcyCheckHistoryQos(const HistoryQosPolicy& qosA, const HistoryQosPolicy& qosB)
{
	return (qosA.kind == qosB.kind) && (qosA.depth == qosB.depth);
}

bool QosPolicyCheck::ConsistebcyCheckResourceLimitsQos(const ResourceLimitsQosPolicy& qosA, const ResourceLimitsQosPolicy& qosB)
{
	return (qosA.max_samples == qosB.max_samples) &&
		   (qosA.max_instances == qosB.max_instances) &&
		   (qosA.max_samples_per_instance == qosB.max_samples_per_instance);
}

bool QosPolicyCheck::ConsistebcyCheckPresentationQos(const PresentationQosPolicy& qosA, const PresentationQosPolicy& qosB)
{
	return (qosA.access_scope == qosB.access_scope) &&
		   (qosA.coherent_access == qosB.coherent_access) &&
		   (qosA.ordered_access == qosB.ordered_access);
}

bool QosPolicyCheck::ConsistebcyCheckDeadlineQos(const DeadlineQosPolicy& qosA, const DeadlineQosPolicy& qosB)
{
	return qosA.period == qosB.period;
}

bool QosPolicyCheck::ConsistebcyCheckTimeBasedFilterQos(const TimeBasedFilterQosPolicy& qosA, const TimeBasedFilterQosPolicy& qosB)
{
	return qosA.minimum_separation == qosB.minimum_separation;
}

void QosPolicyCheck::CheckQosMatchRule(const DataWriterQos& dwQos, const DataReaderQos& drQos, std::set<QosPolicyId_t>& qosPolicyId)
{
	qosPolicyId.clear();
	/* durability设置不匹配 */
	if (dwQos.durability.kind < drQos.durability.kind) {
		qosPolicyId.insert(DURABILITY_QOS_POLICY_ID);
	}
	/* deadline设置不匹配 */
	if (dwQos.deadline.period > drQos.deadline.period) {
		qosPolicyId.insert(DEADLINE_QOS_POLICY_ID);
	}
	if (dwQos.latency_budget.duration > drQos.latency_budget.duration) {
		qosPolicyId.insert(LATENCYBUDGET_QOS_POLICY_ID);
	}
	/* ownership 设置不匹配 */
	if (dwQos.ownership.kind != drQos.ownership.kind) {
		// OWNERSHIP_QOS_POLICY_ID
		qosPolicyId.insert(OWNERSHIP_QOS_POLICY_ID);
	}
	/* 存活性不匹配 */
	if (dwQos.liveliness.kind < drQos.liveliness.kind || dwQos.liveliness.lease_duration > drQos.liveliness.lease_duration) {
		qosPolicyId.insert(LIVELINESS_QOS_POLICY_ID);
	}
	if (BEST_EFFORT_RELIABILITY_QOS == dwQos.reliability.kind && RELIABLE_RELIABILITY_QOS == drQos.reliability.kind) {
		qosPolicyId.insert(RELIABILITY_QOS_POLICY_ID);
	}
	/* DataReader为报文源时间戳排序 DataWriter为报文接收时间戳排序，设置不匹配 */
	if (BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS == drQos.destination_order.kind &&
		BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS == dwQos.destination_order.kind) {
		qosPolicyId.insert(DESTINATIONORDER_QOS_POLICY_ID);
	}
}


